---
category: '@threlte/xr'
title: '<Controller>'
order: 2
type: 'component'
componentSignature:
  {
    events:
      [
        {
          name: 'connected',
          payload: "XRControllerEvent<'connected'>",
          description: 'Fired when the controller connects.'
        },
        {
          name: 'disconnected',
          payload: "XRControllerEvent<'disconnected'>",
          description: 'Fired when the controller disconnects.'
        },
        {
          name: 'select',
          payload: "XRControllerEvent<'select'>",
          description: 'Fired when a the user has completed a primary action.'
        },
        {
          name: 'selectstart',
          payload: "XRControllerEvent<'selectstart'>",
          description: 'Fired when a the user begins a primary action.'
        },
        {
          name: 'selectend',
          payload: "XRControllerEvent<'selectend'>",
          description: 'Fired when a the user ends a primary action or when the controller that is in the process of handling an ongoing primary action is disconnected without successfully completing the action.'
        },
        {
          name: 'squeeze',
          payload: "XRControllerEvent<'squeeze'>",
          description: 'Fired when the controller has completed a primary squeeze action.'
        },
        {
          name: 'squeezestart',
          payload: "XRControllerEvent<'squeezestart'>",
          description: 'Fired when the user begins a primary squeeze action.'
        },
        {
          name: 'squeezeend',
          payload: "XRControllerEvent<'squeezeend'>",
          description: 'Fired when a the user ends a primary squeeze action or when the controller that is in the process of handling an ongoing primary squeeeze action is disconnected without successfully completing the action.'
        }
      ]
  }
---

`<Controller />` represents a `THREE.XRTargetRaySpace`, a `THREE.XRGripSpace`, and a controller model for a specified hand.

```svelte
<Controller left />
<Controller right />
```

It will by default load a controller model that attempts to match the physical controller.

<Tip type="warning">
  Default controller models are fetched from the immersive web group's [webxr input profile
  repo](https://github.com/immersive-web/webxr-input-profiles). If you are developing an offline
  app, you should download and provide any anticipated models.
</Tip>

`<Controller>` can accept three snippets.

If a children snippet is provided, the default controller model will not be rendered, and will be replaced with the children content.

```svelte {2-5}+
<Controller left>
  <T.Mesh>
    <T.IcosahedronGeometry args={[0.2]} />
    <T.MeshStandardMaterial color="turquoise" />
  </T.Mesh>
</Controller>
```

Two additional snippets exist to place children in the controller's [grip space](https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource/gripSpace) and the controller's [target ray space](https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource/targetRaySpace).

```svelte
<Controller left>
  {#snippet grip()}
    <T.Mesh>
      <T.IcosahedronGeometry args={[0.2]} />
      <T.MeshStandardMaterial color="hotpink" />
    </T.Mesh>
  {/snippet}

  {#snippet targetRay()}
    <T.Mesh>
      <T.IcosahedronGeometry args={[0.2]} />
      <T.MeshStandardMaterial color="orange" />
    </T.Mesh>
  {/snippet}
</Controller>
```

<Example path="xr/controller" />
